package com.yidu.logisticssystem.service.impl;

import com.yidu.logisticssystem.dao.LogisticsGateDao;
import com.yidu.logisticssystem.dao.LogisticsStaffDao;
import com.yidu.logisticssystem.dao.LogisticsWageNormDao;
import com.yidu.logisticssystem.entity.LogisticsStaff;
import com.yidu.logisticssystem.entity.LogisticsWage;
import com.yidu.logisticssystem.dao.LogisticsWageDao;
import com.yidu.logisticssystem.entity.LogisticsWageNorm;
import com.yidu.logisticssystem.service.LogisticsWageService;
import com.yidu.logisticssystem.utils.Tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 工资表(LogisticsWage)表服务实现类
 * <p>
 * 还想处理一个如果员工信息已经删掉了，但我的工资页面上还是要显示这条工资信息
 *
 * @author 李彩凤
 * @since 2021-03-08 16:46:58
 */
@Service("logisticsWageService")
public class LogisticsWageServiceImpl implements LogisticsWageService {
    Logger log = LoggerFactory.getLogger(this.getClass());//日志输出
    @Resource
    private LogisticsWageDao logisticsWageDao;
    @Resource
    private LogisticsStaffDao staffDao;
    @Resource
    private LogisticsGateDao gateDao;
    @Resource
    private LogisticsWageNormDao wageNormDao;

    /**
     * 通过ID查询单条数据
     *
     * @param wageId 主键
     * @return 实例对象
     */
    @Override
    public LogisticsWage queryById(Integer wageId) {
        log.info("进来了impl-queryById");
        return this.logisticsWageDao.queryById(wageId);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<LogisticsWage> queryAllByLimit(int offset, int limit) {
        return this.logisticsWageDao.queryAllByLimit(offset, limit);
    }

    /**
     * 通过实体作为筛选条件查询
     *
     * @param logisticsWage 实例对象
     * @return 对象列表
     */
    @Override
    public List<LogisticsWage> queryAll(LogisticsWage logisticsWage) {
        return this.logisticsWageDao.queryAll(logisticsWage);
    }

    /**
     * 通过实体作为筛选条件查询
     *
     * @param findAllWage 筛选条件
     * @return 对象列表
     */
    @Override
    public List<LogisticsWage> findAll(Object findAllWage, String wageMonth) {
        log.info("进来了impl-findAll" + findAllWage + " " + wageMonth);
        List<LogisticsWage> list = this.logisticsWageDao.findAll(findAllWage, wageMonth);//使用dao的findAll方法模糊查询返回wage对象的List集合
        for (LogisticsWage wage : list) {//循环list集合，把对象里查出来的obj值赋给对象
            wage.setStaffName(wage.getStaffObj().getStaffName());//赋值员工姓名
            wage.setStaffNum(wage.getStaffObj().getStaffNum());//赋值员工编号
            wage.setSectionName(wage.getSectionObj().getSectionName());//赋值员工部门
            wage.setPostName(wage.getPostObj().getPostName());//赋值员工职位
            wage.setMapName(wage.getMapObj().getMapName());//赋值地区名
            /*当某员工的薪资标准未设定，已增加该员工时，处理薪资为空*/
            log.info("员工id：" + wage.getStaffId() + " " + "基本工资" + wage.getWageBasepay());
            /*截取当前年月份*/
            SimpleDateFormat sdf = new SimpleDateFormat();//new一个simpleDateFormat对象格式化时间
            sdf.applyPattern("yyyy-MM");// 使用sdf的applyPattern方法定义日期格式为：yyyy-MM-dd
            Date date = new Date();//new一个Date对象取到当前时间
            String month = sdf.format(date);//使用sdf的format方法将当前时间格式化
            /*处理月份为上月*/
            String monthChar = month.substring(month.length() - 1);//使用substring方法取到length（）-1位
            int m = Integer.parseInt(monthChar) - 1;//用包装类Integer把它转换一下并减一个月
            month = month.substring(0, month.length() - 2);//然后再把当前月份的前面部分也截取出来
            month += m;//最后把两个字符串连起来
            log.info("当前年月份：" + month);
            if (wageMonth.equals(month)) {//if wageMonth的年月份与当前年月份相等
                if (wage.getWageBasepay() == 0.0 && wage.getWageAllowance() == 0.0 && wage.getWagePost() == 0.0) {//if 基本工资、岗位工资、补贴都为空
                    LogisticsStaff staff = staffDao.queryById(wage.getStaffId()); //使用staffDao的queryById方法查询该员工
                    if (staff.getPostId() != null && Tools.noEmpty(staff.getMapId())) {//if 员工的职位id和地区id都不为空
                        LogisticsWageNorm norm = wageNormDao.mapAndPost(staff.getPostId(), staff.getMapId());//使用wageNormDao的mapAndPost方法根据该员工地区id和职位id查询单条数据返回norm对象
                        if (norm != null) {//if norm对象不为空
                            wage.setWageBasepay(norm.getNormBasepay());//把norm的基本工资保存到wage对象
                            wage.setWageAllowance(norm.getNormSubsidy());//把norm的补贴保存到wage对象
                            wage.setWagePost(norm.getNormPost());//把norm的岗位工资保存到wage对象
                            update(wage);//将新工资保存到数据库
                        }
                    }
                }
            }

        }
        return list;
    }

    /**
     * 批量新增或按主键更新数据（MyBatis原生foreach方法）
     *
     * @param entities List<LogisticsWage> 实例对象列表
     * @return 影响行数
     */
    @Override
    public LogisticsWage insertOrUpdateBatch(List<LogisticsWage> entities) {
        return null;
    }

    /**
     * 非空增加列
     *
     * @param logisticsWage 实例对象
     * @return 影响的行数
     */
    @Transactional//注解：事务
    @Override
    public int insertSelective(LogisticsWage logisticsWage) {
        log.info("进来了impl-insertSelective");
        LogisticsWage wage = null;//定义一个null的wage对象
        int row = 0;//定义一个行数变量
        log.info(logisticsWage.getWageMonth());
        int rows = logisticsWageDao.findMonth(logisticsWage.getWageMonth());//使用wageDao的findMonth方法查询月份，返回查询到的行数
        if (rows < 1) {//if行数<1，本月工资数据未增加
            List<LogisticsStaff> staffs = staffDao.findAll(); //使用staffDao的findAll方法查询所有员工
            log.info(staffs.size() + "位员工");
            for (LogisticsStaff staff : staffs) {//循环取出员工
                /*处理自动赋值：须查询该员工编号，员工职位，员工姓名，员工部门，本月总工时，norm表*/
                wage = new LogisticsWage();//每循环一次new一个新的wage对象
                wage.setStaffId(staff.getStaffId());//把员工id保存到wage对象
                wage.setWageMonth(logisticsWage.getWageMonth());//年月份保存到wage对象
                LogisticsWageNorm norm = wageNormDao.mapAndPost(staff.getPostId(), staff.getMapId());//使用wageNormDao的mapAndPost方法根据地区id和职位id查询单条数据返回norm对象
                if (norm != null) {//if norm对象不为空
                    wage.setWageBasepay(norm.getNormBasepay());//把norm的基本工资保存到wage对象
                    wage.setWageAllowance(norm.getNormSubsidy());//把norm的补贴保存到wage对象
                    wage.setWagePost(norm.getNormPost());//把norm的岗位工资保存到wage对象
                }
                Integer time = gateDao.sumTime(logisticsWage.getWageMonth(), staff.getStaffNum());//使用gateDao的sumTime方法员工编号计算该员工本月总工时
                wage.setGateTime(time);//把本月总工时保存到wage对象
                /* 工资算法  （保留两位小数）*/
                DecimalFormat decimalFormat = new DecimalFormat();//new一个DecimalFormat类
                decimalFormat.setMaximumFractionDigits(2);//setMaximumFractionDigits()方法：保留几位小数
                decimalFormat.setGroupingSize(0);//setGroupingSize()方法：小数点左边的数，按每几位用逗号分隔 如12,34,56.789
                decimalFormat.setRoundingMode(RoundingMode.FLOOR);//setRoundingMode()方法：舍入模式，百度的填RoundingMode.FLOOR就行,意思是不四舍五入
                if (wage.getWageBasepay() == null) {//if wage的WageBasepay为空
                    wage.setWageBasepay(0.00);//赋值0.00
                }
                if (wage.getWagePost() == null) {//if wagePost为空
                    wage.setWagePost(0.00);
                }
                if (wage.getWageAllowance() == null) {//if wageAllowance为空
                    wage.setWageAllowance(0.00);
                }
                /*计算应发工资 = 基本工资+岗位工资+补贴*/
                double wageSalary = wage.getWageBasepay() + wage.getWagePost() + wage.getWageAllowance();
                wage.setWageSalary(Double.valueOf(decimalFormat.format(wageSalary)));//decimalFormat.format()方法保留两位小数，返回字符串，所以需要用包装类转一下，再保存到应发工资wageSalary
                log.info("应发工资：" + wageSalary);
                /*计算五险一金 （*0.222然后保留两位，再转Double包装类）*/
                double tax = Double.parseDouble(decimalFormat.format(wageSalary * 0.222));
                wage.setWageTax(tax);//保存到五险一金wageTax
                log.info("五险一金：" + tax);
                /*计算实发工资：应发工资 - 五险一金*/
                double sum = wageSalary - tax;
                if (sum < 0) {//处理负工资
                    sum = 0.00;
                }
                wage.setWageSum(Double.valueOf(decimalFormat.format(sum)));//把实发工资保留两位，转Double包装类，保存到实发工资wageSum
                log.info("实发工资：" + sum);
                row += logisticsWageDao.insertSelective(wage);//使用wageDao的insertSelective方法添加进数据库
            }
        } else {
            log.info("本月员工薪资数据已经生成过了");
        }
        return row;
    }

    /**
     * 修改数据
     *
     * @param wage 实例对象
     * @return 修改后的实例对象
     */
    @Transactional//注解：事务
    @Override
    public LogisticsWage update(LogisticsWage wage) {
        log.info("进来了impl-update");
        /*工资算法  （保留两位小数）*/
        DecimalFormat decimalFormat = new DecimalFormat();//new一个DecimalFormat类
        decimalFormat.setMaximumFractionDigits(2);//setMaximumFractionDigits()方法：保留几位小数
        decimalFormat.setGroupingSize(0);//setGroupingSize()方法：小数点左边的数，按每几位用逗号分隔 如12,34,56.789
        decimalFormat.setRoundingMode(RoundingMode.FLOOR);//setRoundingMode()方法：舍入模式，百度的填RoundingMode.FLOOR就行,意思是不四舍五入
        /*计算应发工资 = 基本工资+岗位工资+补贴+加班补助*/
        log.info(wage.getWageBasepay() + " " + wage.getWagePost() + " " + wage.getWageAllowance() + " " + wage.getWageOverTime());
        double wageSalary = wage.getWageBasepay() + wage.getWagePost() + wage.getWageAllowance() + wage.getWageOverTime();
        wage.setWageSalary(Double.valueOf(decimalFormat.format(wageSalary)));//decimalFormat.format()方法保留两位小数，返回字符串，所以需要用包装类转一下，再保存到应发工资wageSalary
        log.info("应发工资：" + wageSalary);
        /*计算五险一金 （*0.222的税率然后保留两位，再转Double包装类）*/
        Double tax = Double.valueOf(decimalFormat.format(wageSalary * 0.222));
        wage.setWageTax(tax);//保存到五险一金wageTax
        log.info("五险一金：" + tax);
        /*计算实发工资：应发工资-五险一金-其他扣款*/
        double sum = wageSalary - tax - wage.getWageElse();
        if (sum < 0) {//处理负工资
            sum = 0.00;
        }
        wage.setWageSum(Double.valueOf(decimalFormat.format(sum)));//把实发工资保留两位，转Double包装类，保存到实发工资wageSum
        log.info("实发工资：" + sum);
        /*使用wageDao的update方法修改进数据库*/
        int row = logisticsWageDao.update(wage);
        return this.queryById(wage.getWageId());
    }

    /**
     * 通过年月份删除数据
     *
     * @param month 年月份
     * @return 影响行数
     */
    @Override
    public int deleteAll(String month) {
        log.info("进来了impl+deleteAll");
        return this.logisticsWageDao.deleteAll(month);
    }
}
